﻿/*
* 创建者：LIYINFAI
* 创建时间：2023/10/15 11:40:00
* 描述：
* --------------------------------------
* 修改说明：
* --------------------------------------
*/
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;

namespace CommonLibrary
{
    /// <summary>
    /// 氦检相关PLC配置
    /// </summary>
    public class HeliumPLCEntity
    {
        /// <summary>
        /// 备注
        /// </summary>
        [Description("备注")]
        [JsonProperty(PropertyName = "remark")]
        public string Remark { get; set; } = string.Empty;
        /// <summary>
        /// 触发氦检仓背景检测地址
        /// </summary>
        [Description("触发氦检仓背景检测地址")]
        [JsonProperty(PropertyName = "triggerBackgroudAddress")]
        public string TriggerBackgroudAddress { get; set; } = string.Empty;
        /// <summary>
        /// 氦检仓背景判断反馈地址
        /// </summary>
        [Description("氦检仓背景判断反馈地址")]
        [JsonProperty(PropertyName = "backgroudJudgeAddress")]
        public string BackgroudJudgeAddress { get; set; } = string.Empty;
        /// <summary>
        /// 触发氦检仓氦检测试地址
        /// </summary>

        [Description("触发氦检仓氦检测试地址")]
        [JsonProperty(PropertyName = "triggerHeliumAddress")]
        public string TriggerHeliumAddress { get; set; } = string.Empty;
        /// <summary>
        /// 氦检仓氦检判断反馈地址
        /// </summary>
        [Description("氦检仓氦检判断反馈地址")]
        [JsonProperty(PropertyName = "heliumJudgeAddress")]
        public string HeliumJudgeAddress { get; set; } = string.Empty;


        /// <summary>
        /// 是否允许读取地址
        /// </summary>
        [Description("是否允许读取地址")]
        [JsonProperty(PropertyName = "readPermitAddress")]
        public string ReadPermitAddress { get; set; } = string.Empty;

        /// <summary>
        /// 漏率地址
        /// </summary>
        [Description("漏率地址")]
        [JsonProperty(PropertyName = "leakValueAddress")]
        public string LeakValueAddress { get; set; } = string.Empty;
        /// <summary>
        /// 检漏口压力地址
        /// </summary>
        [Description("检漏口压力地址")]
        [JsonProperty(PropertyName = "pressValueAddress")]
        public string PressValueAddress { get; set; } = string.Empty;
        /// <summary>
        /// 氦检时间地址
        /// </summary>
        [Description("氦检时间地址")]
        [JsonProperty(PropertyName = "heliumTimesAddress")]
        public string HeliumTimesAddress { get; set; } = string.Empty;
        /// <summary>
        /// 氦检结果地址
        /// </summary>
        [Description("氦检结果地址")]
        [JsonProperty(PropertyName = "heliumResultAddress")]
        public string HeliumResultAddress { get; set; } = string.Empty;
        /// <summary>
        /// 描述信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return CommonHelper.GetObjectString(this);
        }
    }
    /// <summary>
    /// 氦检TCP相关参数
    /// </summary>
    public class HeliumTcpParam : TcpParameter
    {
        /// <summary>
        /// 触发地址与结果
        /// </summary>
        [Description("触发地址与结果")]
        [JsonProperty(PropertyName = "PLCEntities")]
        public List<HeliumPLCEntity> PLCEntities = new List<HeliumPLCEntity>();
        /// <summary>
        /// 描述信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return CommonHelper.GetObjectString(this);
        }
    }
    /// <summary>
    /// 氦检串口相关参数
    /// </summary>
    public class HeliumComParam : ComParameter
    {
        /// <summary>
        /// 触发地址与结果
        /// </summary>
        [Description("触发地址与结果")]
        [JsonProperty(PropertyName = "PLCEntities")]
        public List<HeliumPLCEntity> PLCEntities = new List<HeliumPLCEntity>();
        /// <summary>
        /// 描述信息
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return CommonHelper.GetObjectString(this);
        }
    }
    /// <summary>
    /// 消息通知代理
    /// </summary>
    /// <param name="status"></param>
    /// <param name="press"></param>
    /// <param name="rate"></param>
    public delegate void NotifyHeliumHelperJobDelegate(string status, string press, string rate);
    /// <summary>
    /// 氦检仪操作类
    /// </summary>
    public class HeliumHelper : BaseHelper
    {
        /// <summary>
        /// 串口配置文件
        /// </summary>
        static string heliumComConfigPath = Path.Combine(CommonHelper.COMMON_CONFIG_DIR, "HeliumComConfig.json");
        /// <summary>
        /// TCP配置文件
        /// </summary>
        static string heliumTcpConfigPath = Path.Combine(CommonHelper.COMMON_CONFIG_DIR, "HeliumTcpConfig.json");
        #region auto com
        /// <summary>
        /// 获取串口配置内容
        /// </summary>
        /// <returns></returns>
        public static List<HeliumComParam> GetComHeliumConfig()
        {
            return CommonHelper.GetJsonListFromFile<HeliumComParam>(heliumComConfigPath);
        }
        /// <summary>
        /// 保存串口配置内容
        /// </summary>
        /// <param name="list"></param>
        public static void SaveComHeliumConfig(List<HeliumComParam> list)
        {
            CommonHelper.SaveToJsonFile(list, heliumComConfigPath);
        }
        #endregion
        #region auto tcp
        /// <summary>
        /// 获取Tcp配置内容
        /// </summary>
        /// <returns></returns>
        public static List<HeliumTcpParam> GetTcpHeliumConfig()
        {
            return CommonHelper.GetJsonListFromFile<HeliumTcpParam>(heliumTcpConfigPath);
        }
        /// <summary>
        /// 保存Tcp配置内容
        /// </summary>
        /// <param name="list"></param>
        public static void SaveTcpHeliumConfig(List<HeliumTcpParam> list)
        {
            CommonHelper.SaveToJsonFile(list, heliumTcpConfigPath);
        }
        #endregion
        /// <summary>
        /// 构造函数
        /// </summary>
        public HeliumHelper()
        {
            this.CustomSelfCheckHandler = () =>
            {
                if (this.IsConnected && !string.IsNullOrWhiteSpace(this.StatusAddress))
                {
                    try
                    {
                        string status = "";
                        this.Status = ReadStatus(out status);
                        //防止氦检仪返回异常数据，二次读取
                        if (this.Status != (short)1)
                        {
                            this.Status = ReadStatus(out status);
                        }
                        this.StatusString = status;
                        this.LeakPressString = ReadLeakPressure();
                        this.LeakRateString = ReadLeakRate();

                        var heliumConfig = HeliumConfig.Instance();
                        short allow = this.IsValidStatus && this.LeakRate <= heliumConfig.BackgroundRate ? (short)1 : (short)0;


                        List<string> readPermits = new List<string>();
                        if (this.TriggerHandlers != null && this.TriggerHandlers.Count > 0)
                        {
                            foreach (var handler in this.TriggerHandlers)
                            {
                                if (handler.OtherAddress is HeliumCheckPLCEntity)
                                {
                                    var item = handler.OtherAddress as HeliumCheckPLCEntity;
                                    if (item != null && !string.IsNullOrWhiteSpace(item.ReadPermitAddress)
                                    && !readPermits.Contains(item.ReadPermitAddress))
                                    {
                                        readPermits.Add(item.ReadPermitAddress);
                                    }
                                }
                            }
                        }
                        StatusHandler(readPermits, allow);
                        LogHelper.Info($"状态：{this.StatusString}, 压力：{this.LeakPressString}, 漏率：{this.LeakRateString}");
                        if (NotifyHeliumHelperJob != null)
                        {
                            NotifyHeliumHelperJob(this.StatusString, this.LeakPressString, this.LeakRateString);
                        }
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }

                }
            };
        }
        /// <summary>
        /// 消息通知处理
        /// </summary>
        public NotifyHeliumHelperJobDelegate NotifyHeliumHelperJob { get; set; } = null;
        #region 每个Helper特定的参数
        /// <summary>
        /// 通讯超时时间，默认1000毫秒
        /// </summary>
        public override int CommunicationTimeout => BusinessConfig.Instance().HeliumTimeout;
        /// <summary>
        /// 状态（字符串）
        /// </summary>
        public string StatusString { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        public short Status { get; set; }
        /// <summary>
        /// 漏率（字符串）
        /// </summary>
        public string LeakRateString { get; set; }
        /// <summary>
        /// 漏率
        /// </summary>
        public float LeakRate
        {
            get
            {
                float result = 0;
                if (!string.IsNullOrWhiteSpace(this.LeakRateString))
                {
                    if (!float.TryParse(this.LeakRateString, out result))
                    {
                        result = 0;
                    }
                }
                return result;
            }
        }
        /// <summary>
        /// 压力（字符串）
        /// </summary>
        public string LeakPressString { get; set; }
        /// <summary>
        /// 压力
        /// </summary>
        public float LeakPress
        {
            get
            {
                float result = 0;
                if (!string.IsNullOrWhiteSpace(this.LeakPressString))
                {
                    if (!float.TryParse(this.LeakPressString, out result))
                    {
                        result = 0;
                    }
                }
                return result;
            }
        }
        /// <summary>
        /// 状态是否正常
        /// </summary>
        public bool IsValidStatus => this.Status == (short)1;
        #endregion

        /// <summary>
        /// 状态检测
        /// </summary>
        private void StatusHandler(List<string> readPermitAddresses, short allow)
        {
            var param = new HeliumExcuteEntity()
            {
                Status = this.Status,
                OtherAddress = this.StatusAddress,
                ReadPermitAddresses = readPermitAddresses,
                AllowReadPermit = allow
            };
            CommonHelper.GetJson(PluginManager.Instance.Excute(this.Name, "HELIUM_STATUS", CommonHelper.GetJsonString(param, Formatting.None)), param);
        }
        /// <summary>
        /// 背景漏率检测
        /// </summary>
        /// <param name="result"></param>
        /// <param name="leakRate"></param>
        /// <param name="entity"></param>
        /// <param name="isNormal"></param>
        private void BusinessBackRateHandler(ref short result, float leakRate, HeliumBackRatePLCEntity entity, bool isNormal)
        {
            var param = new HeliumExcuteEntity()
            {
                IsNormal = isNormal,
                LeakRate = leakRate,
                OtherAddress = CommonHelper.GetJsonString(entity, Formatting.None)
            };
            param = CommonHelper.GetJson(PluginManager.Instance.Excute(this.Name, "HELIUM_BACKRATE", CommonHelper.GetJsonString(param, Formatting.None)), param);
            result = param.Result;
        }
        /// <summary>
        /// 氦检检测
        /// </summary>
        /// <param name="result"></param>
        /// <param name="leakRate"></param>
        /// <param name="leakPress"></param>
        /// <param name="entity"></param>
        /// <param name="isNormal"></param>
        private void BusinessHeliumHandler(ref short result, float leakRate, float leakPress, HeliumCheckPLCEntity entity, bool isNormal)
        {
            var param = new HeliumExcuteEntity()
            {
                IsNormal = isNormal,
                LeakRate = leakRate,
                LeakPress = leakPress,
                OtherAddress = CommonHelper.GetJsonString(entity, Formatting.None)
            };
            param = CommonHelper.GetJson(PluginManager.Instance.Excute(this.Name, "HELIUM_HELIUM", CommonHelper.GetJsonString(param, Formatting.None)), param);
            result = param.Result;
        }
        /// <summary>
        /// 氦检仪逻辑
        /// </summary>
        /// <param name="handlerName"></param>
        /// <param name="handlerType"></param>
        /// <param name="otherAddress"></param>
        /// <param name="otherData"></param>
        public override void RealHandler(string handlerName, EHandlerType handlerType, object otherAddress, object otherData)
        {
            short result = 2;
            float leakRate = 0.00f;
            float leakPress = 0.00f;
            if (this.IsConnected)
            {
                bool isNormal = false;
                Stopwatch stopwatch = Stopwatch.StartNew();
                try
                {
                    HeliumConfig heliumConfig = HeliumConfig.Instance();
                    if (handlerType.Equals(EHandlerType.HELIUM_BACKLEAKRATE))
                    {
                        this.RealShowMessage($"【{this.Name}】{handlerName}");
                        if (this.IsValidStatus)
                        {
                            this.LeakRateString = ReadLeakRate();
                            float tempValue = 0.00f;
                            if (float.TryParse(this.LeakRateString, out tempValue))
                            {
                                isNormal = true;
                                leakRate = this.LeakRate;
                            }
                            LogHelper.Info($"【{this.Name}】漏率：{this.LeakRateString}");
                        }
                        else
                        {
                            LogHelper.Info($"【{this.Name}】氦检仪状态不正确");
                            this.RealShowMessage($"【{this.Name}】氦检仪状态不正确", false);
                        }
                    }
                    else if (handlerType.Equals(EHandlerType.HELIUM_HELIUM))
                    {
                        LogHelper.Info($"【{this.Name}】触发氦检，超时时间：{this.CommunicationTimeout}");
                        this.RealShowMessage($"【{this.Name}】{handlerName}");
                        if (this.IsValidStatus)
                        {
                            this.LeakRateString = ReadLeakRate();
                            this.LeakPressString = ReadLeakPressure();
                            float tempPressValue = 0.00f, tempRateValue = 0.00f;
                            bool normalLeake = false;
                            bool normalPress = false;
                            if (float.TryParse(this.LeakRateString, out tempRateValue))
                            {
                                leakRate = this.LeakRate;
                                normalLeake = true;
                            }
                            else
                            {
                                LogHelper.Info($"【{this.Name}】 二次读取漏率");
                                this.LeakRateString = ReadLeakRate();
                                if (float.TryParse(this.LeakRateString, out tempRateValue))
                                {
                                    leakRate = this.LeakRate;
                                    normalLeake = true;
                                }
                            }
                            if (float.TryParse(this.LeakPressString, out tempPressValue))
                            {
                                leakPress = this.LeakPress;
                                normalPress = true;
                            }
                            else
                            {
                                LogHelper.Info($"【{this.Name}】 二次读取压力");
                                this.LeakPressString = ReadLeakPressure();
                                if (float.TryParse(this.LeakPressString, out tempPressValue))
                                {
                                    leakPress = this.LeakPress;
                                    normalPress = true;
                                }
                            }
                            isNormal = normalLeake && normalPress;
                            LogHelper.Info($"【{this.Name}】漏率：{this.LeakRateString}，压力：{this.LeakPressString}");
                        }
                        else
                        {
                            LogHelper.Info($"【{this.Name}】氦检仪状态不正确");
                            this.RealShowMessage($"【{this.Name}】氦检仪状态不正确", false);
                        }
                    }
                }
                catch (Exception ex)
                {
                    isNormal = false;
                    LogHelper.Error(ex);
                }
                finally
                {
                    stopwatch.Stop();
                    if (handlerType.Equals(EHandlerType.HELIUM_BACKLEAKRATE))
                    {
                        HeliumBackRatePLCEntity entity = otherAddress as HeliumBackRatePLCEntity;
                        BusinessBackRateHandler(ref result, leakRate, entity, isNormal);
                        this.RealShowMessage($"【{this.Name}】背景漏率判定检测，耗时：{stopwatch.ElapsedMilliseconds} 毫秒，结果：{(result == (short)ENGCode.OK ? "OK" : "NG")}。", result == (short)ENGCode.OK);
                    }
                    else if (handlerType.Equals(EHandlerType.HELIUM_HELIUM))
                    {
                        HeliumCheckPLCEntity entity = otherAddress as HeliumCheckPLCEntity;
                        BusinessHeliumHandler(ref result, leakRate, leakPress, entity, isNormal);
                        this.RealShowMessage($"【{this.Name}】氦检，耗时：{stopwatch.ElapsedMilliseconds} 毫秒，漏率：{CommonHelper.GetScientificNotation(leakRate)}，检漏口压力：{CommonHelper.GetScientificNotation(leakPress)}，结果：{(result == (short)ENGCode.OK ? "OK" : "NG")}。", result == (short)ENGCode.OK);
                    }
                }
            }
        }

        /// <summary>
        /// 读取压力
        /// </summary>
        private string ReadLeakPressure()
        {
            string result = "0.00E+00";
            result = this.CommunicationType.Equals(ECommunicationType.SERIAL) ? RunComCommand("G3\r") : RunTcpCommand("G3\r"); //读取检漏口压力，字符串型
            result = string.IsNullOrWhiteSpace(result) ? "通讯异常" : result;
            float value = 0;
            if (float.TryParse(result, out value))
            {
                result = CommonHelper.GetScientificNotation(value);
            }
            return result;
        }
        /// <summary>
        /// 读取漏率
        /// </summary>
        public string ReadLeakRate()
        {
            string result = "0.00E+00";
            result = this.CommunicationType.Equals(ECommunicationType.SERIAL) ? RunComCommand("G1\r") : RunTcpCommand("G1\r"); //读取漏率,字符串型    
            result = string.IsNullOrWhiteSpace(result) ? "通讯异常" : result;
            float value = 0;
            if (float.TryParse(result, out value))
            {
                result = CommonHelper.GetScientificNotation(value);
            }
            return result;
        }
        /// <summary>
        /// 读取状态
        /// </summary>
        /// <param name="status"></param>
        /// <returns></returns>
        private short ReadStatus(out string status)
        {
            status = this.CommunicationType.Equals(ECommunicationType.SERIAL) ? RunComCommand("S1\r") : RunTcpCommand("S1\r");
            status = string.IsNullOrWhiteSpace(status) ? "通讯异常" : status;
            status = !string.IsNullOrWhiteSpace(status) ? status.ToUpper() : status;
            short result = 0;
            switch (status)
            {
                case "MEAS"://检漏状态
                    result = 1;
                    break;
                case "STBY"://待机状态
                    result = 2;
                    break;
                case "CALI"://标定状态
                    result = 3;
                    break;
                case "ACCL"://启动中状态
                    result = 4;
                    break;
                case "ERRO"://出错状态
                    result = 6;
                    break;
                case "ER21"://出错状态
                    result = 7;
                    break;
                case "E2"://出错状态
                    result = 8;
                    break;
                case "TSTC"://测试标漏状态
                    result = 5;
                    break;
                default://异常
                    result = 0;
                    break;
            }
            return result;
        }
    }
}
